package com.yykj.hospital.server.service.impl;

import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.google.common.base.Joiner;
import com.yykj.common.enums.ResultEnums;
import com.yykj.common.exception.NormalException;
import com.yykj.common.util.LocalObjectUtil;
import com.yykj.common.util.PageRequestUtil;
import com.yykj.common.vo.PageData;
import com.yykj.hospital.server.dto.HospitalLabelImportDTO;
import com.yykj.hospital.server.form.HospitalDoctorBindLabelListForm;
import com.yykj.hospital.server.form.HospitalLabelBindForm;
import com.yykj.hospital.server.form.HospitalLabelListForm;
import com.yykj.hospital.server.model.entity.HospitalDoctor;
import com.yykj.hospital.server.model.entity.HospitalDoctorBindLabel;
import com.yykj.hospital.server.model.entity.HospitalLabel;
import com.yykj.hospital.server.model.repository.HospitalDoctorBindLabelRepository;
import com.yykj.hospital.server.model.repository.HospitalDoctorRepository;
import com.yykj.hospital.server.model.repository.HospitalLabelRepository;
import com.yykj.hospital.server.service.HospitalLabelService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

/**
 * Created by chendg
 * on 2021/10/31 0031.
 */
@Service
public class HospitalLabelServiceImpl implements HospitalLabelService {
    @Override
    public HospitalLabel editHospitalLabel(HospitalLabel label) {
        if (label.getHospitalId() == null || label.getHospitalId() <= 0) {
            throw new NormalException(ResultEnums.PARAM_ERROR);
        }
        HospitalLabel oldLabel = null;
        if (!StringUtils.isEmpty(label.getName())) {
            oldLabel = hospitalLabelRepository.findFirstByHospitalIdAndName(label.getHospitalId(), label.getName());
            if (oldLabel != null && (!oldLabel.getId().equals(label.getId()) || label.getId() == null || label.getId() == 0)) {
                throw new NormalException(ResultEnums.ALL_READY_EXIST, "标签名称已经存在");
            }
        }

        HospitalLabel hospitalLabel;

        if (label.getId() != null && label.getId() > 0) {
            hospitalLabel = hospitalLabelRepository.findById(label.getId()).orElseThrow(() -> new NormalException(ResultEnums.NOT_EXIST));
            LocalObjectUtil.copyNullValue(label, hospitalLabel);

        } else {

            hospitalLabel = new HospitalLabel();
            BeanUtils.copyProperties(label, hospitalLabel);
        }
        hospitalLabel = hospitalLabelRepository.save(hospitalLabel);
        return hospitalLabel;
    }

    @Override
    public PageData<HospitalLabel> listHospitalLabel(HospitalLabelListForm form) {
        PageRequest pageRequest = PageRequest.of(PageRequestUtil.getPage(form.getCurrentPage()), form.getPageSize());
        Page<HospitalLabel> list;
        if (StringUtils.isEmpty(form.getName())) {
            list = hospitalLabelRepository.findAllByHospitalIdOrderBySorting(form.getHospitalId(), pageRequest);
        } else {
            list = hospitalLabelRepository.findAllByHospitalIdAndNameLikeOrderBySorting(form.getHospitalId(), "%" + form.getName() + "%", pageRequest);
        }
        return PageData.formatList(list, form.getCurrentPage(), form.getPageSize());
    }

    @Override
    public List<HospitalLabel> listAllHospitalLabel(Integer hospitalId) {
        return  hospitalLabelRepository.findAllByHospitalIdOrderBySorting(hospitalId);
    }

    @Override
    public boolean checkHospitalLabelList(Integer hospitalId, ExcelImportResult<HospitalLabelImportDTO> result) {
        Iterator<HospitalLabelImportDTO> iterator = result.getList().iterator();
        HospitalLabelImportDTO dto;
        List<HospitalLabel> allByHospitalId = hospitalLabelRepository.findAllByHospitalId(hospitalId);
        Map<String, HospitalLabel> map = new HashMap<>();
        for (HospitalLabel label : allByHospitalId) {
            map.put(label.getName(), label);
        }
        while (iterator.hasNext()) {
            dto = iterator.next();
            HospitalLabel label = map.get(dto.getName());
            if (label != null) {
                dto.setErrorMsg(dto.getName() + "已经存在");
                iterator.remove();
                result.getFailList().add(dto);
            }
        }

        return result.getFailList().size() == 0;
    }

    @Override
    public void importHospitalLabelList(Integer hospitalId, List<HospitalLabelImportDTO> list) {
        for (HospitalLabelImportDTO dto : list) {
            HospitalLabel label = new HospitalLabel();
            label.setHospitalId(hospitalId);
            label.setName(dto.getName());
            label.setSorting(dto.getSorting());
            hospitalLabelRepository.save(label);
        }
    }

    @Override
    public void bindHospitalLabel(HospitalLabelBindForm form) {
        if (form.getHospitalId() == null || form.getHospitalId() <= 0
                || form.getDoctorIds() == null || form.getDoctorIds().size() == 0
                || form.getLabelIds() == null || form.getLabelIds().size() == 0) {
            throw new NormalException(ResultEnums.PARAM_ERROR);
        }
        List<HospitalDoctorBindLabel> list = new ArrayList<>();
        List<HospitalDoctor> doctorList = doctorRepository.findAllByHospitalIdAndDoctorIdIn(form.getHospitalId(), form.getDoctorIds());
        Map<String, HospitalDoctor> doctorMap = new HashMap<>();
        for (HospitalDoctor doctor : doctorList) {
            doctorMap.put(doctor.getDoctorId(), doctor);
        }
        List<HospitalLabel> labelList = hospitalLabelRepository.findAllByHospitalId(form.getHospitalId());
        Map<Integer, String> labelMap = new HashMap<>();
        for (HospitalLabel label : labelList) {
            labelMap.put(label.getId(), label.getName());
        }
        List<String> nameList = new ArrayList<>();
        for (Integer labelId : form.getLabelIds()) {
            nameList.add(labelMap.get(labelId));
        }
        String labelIds = Joiner.on(",").join(form.getLabelIds());
        String labelNames = Joiner.on(",").join(nameList);

        List<HospitalDoctorBindLabel> oldList = bindLabelRepository.findAllByHospitalIdAndDoctorIdIn(form.getHospitalId(), form.getDoctorIds());

        Map<String,HospitalDoctorBindLabel> oldMap = new HashMap<>();
        for (HospitalDoctorBindLabel label:oldList){
            oldMap.put(label.getDoctorId(),label);
        }

        for (String doctorId : form.getDoctorIds()) {
            HospitalDoctorBindLabel bindLabel = oldMap.getOrDefault(doctorId,null);
            if(bindLabel == null){
                bindLabel = new HospitalDoctorBindLabel();
                HospitalDoctor hospitalDoctor = doctorMap.get(doctorId);
                BeanUtils.copyProperties(hospitalDoctor, bindLabel);
            }
            bindLabel.setLabelIds(labelIds);
            bindLabel.setLabelNames(labelNames);
            list.add(bindLabel);
        }
        bindLabelRepository.saveAll(list);
    }

    @Override
    public void deleteBindHospitalLabel(Integer id) {
        bindLabelRepository.deleteById(id);
    }

    @Override
    public PageData<HospitalDoctorBindLabel> listBindHospitalLabel(HospitalDoctorBindLabelListForm form) {
        PageRequest pageRequest = PageRequest.of(PageRequestUtil.getPage(form.getCurrentPage())
                , PageRequestUtil.getSize(PageRequestUtil.getSize(form.getPageSize())));

        Page<HospitalDoctorBindLabel> bindLabelPage = bindLabelRepository.findAll(new Specification<HospitalDoctorBindLabel>() {
            @Override
            public Predicate toPredicate(Root<HospitalDoctorBindLabel> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();
                predicateList.add(builder.equal(root.get("hospitalId"), form.getHospitalId()));
                if (!StringUtils.isEmpty(form.getName())) {
                    predicateList.add(builder.like(root.get("labelNames"), "%" + form.getName() + "%"));
                }

                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        }, pageRequest);

        return PageData.formatList(bindLabelPage, PageRequestUtil.getPage(form.getCurrentPage()), PageRequestUtil.getSize(form.getPageSize()));



    }

    private HospitalLabelRepository hospitalLabelRepository;

    private HospitalDoctorRepository doctorRepository;

    private HospitalDoctorBindLabelRepository bindLabelRepository;

    @Autowired
    public void setHospitalLabelRepository(HospitalLabelRepository hospitalLabelRepository) {
        this.hospitalLabelRepository = hospitalLabelRepository;
    }

    @Autowired
    public void setDoctorRepository(HospitalDoctorRepository doctorRepository) {
        this.doctorRepository = doctorRepository;
    }

    @Autowired
    public void setBindLabelRepository(HospitalDoctorBindLabelRepository bindLabelRepository) {
        this.bindLabelRepository = bindLabelRepository;
    }
}
